package cn.texous.starter.sms.handler;

import cn.texous.starter.sms.config.properties.SmsProperties;
import cn.texous.starter.sms.config.properties.TencentSmsProperties;
import cn.texous.starter.sms.model.SendInfo;
import cn.texous.starter.sms.model.SendResult;
import cn.texous.starter.sms.model.SendTempParam;
import com.github.qcloudsms.SmsSingleSender;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * insert description here
 *
 * @author Showa.L
 * @since 2019/8/23 10:55
 */
@Slf4j
public class TencentSmsHandler implements SmsHandler {
    private static final String CHANNEL = "tencent-sms";

    private SmsProperties smsProperties;
    private TencentSmsProperties tencentSmsProperties;

    public TencentSmsHandler(SmsProperties smsProperties) {
        this.smsProperties = smsProperties;
        this.tencentSmsProperties = smsProperties.getTencent();
    }

    @Override
    public SendResult send(SendInfo sendInfo) {
        SendResult sendResult = new SendResult(CHANNEL);
        try {

            SmsSingleSender ssender = new SmsSingleSender(
                    tencentSmsProperties.getAppid(), tencentSmsProperties.getAppkey());
            int templateId = Integer.parseInt(smsProperties
                    .getTemplate().getTencent().get(sendInfo.getTemplate()));
            SmsSingleSenderResult result = ssender.sendWithParam(sendInfo.getNationCode(),
                    sendInfo.getMobile(), templateId, getParam(sendInfo.getParams()),
                    tencentSmsProperties.getSignName(), "", "");

            log.info(result.toString());

            if (result.result == 0) {
                log.info("腾讯云 短信发送成功！");
                sendResult.setCode(SendResult.SUCCESS);
                return sendResult;
            }
            log.error("腾讯云 短信发送失败：{}", new Gson().toJson(sendInfo));
            generatorErrorMessage(sendResult, result);
        } catch (Exception e) {
            log.error(String.format("腾讯云 短信发送失败：%s", e.getMessage()), e);
            sendResult.setErrorCode("0");
            sendResult.setErrorMsg("短信验证码发送失败！");
        }
        return sendResult;
    }

    @Override
    public String channel() {
        return CHANNEL;
    }

    @Override
    public boolean init() {
        return tencentSmsProperties.getInit();
    }

    @Override
    public int order() {
        return tencentSmsProperties.getOrder();
    }

    private static String[] getParam(List<SendTempParam> params) {
        if (params == null || params.isEmpty())
            return new String[]{};
        String[] ps = new String[params.size()];
        params.sort(Comparator.comparing(SendTempParam::getIndex));
        for (int i = 0; i < params.size(); i++) {
            ps[i] = params.get(i).getValue();
        }
        return ps;
    }

    private static void generatorErrorMessage(SendResult result, SmsSingleSenderResult response) {
        int code = response.result;
        String message = errorCodeMap.get(code);
        result.setErrorCode(String.valueOf(code));
        result.setErrorMsg(message);
    }

    private static Map<Integer, String> errorCodeMap = new HashMap<>();

    static {
        errorCodeMap.put(1001, "sig 校验失败，请核对 API 的 sig 格式说明");
        errorCodeMap.put(1002, "短信内容中含有敏感词，请联系 sms helper 沟通解决");
        errorCodeMap.put(1003, "请求包体没有 sig 字段或 sig 为空，请遵守 API 接口说明规范");
        errorCodeMap.put(1004, "请求包解析失败，通常情况下是由于没有遵守 API 接口说明规范导致的，请参考 1004错误详解");
        errorCodeMap.put(1006, "请求没有权限，请查看错误提示语说明，如还有问题请联系 sms helper 并提供失败手机号");
        errorCodeMap.put(1007, "其他错误，请查看错误提示语说明，如还有问题请 sms helper 并提供失败手机号联系");
        errorCodeMap.put(1008, "请求下发短信超时，出现概率很低，可重试解决");
        errorCodeMap.put(1009, "请求 IP 不在白名单中，您配置了校验请求来源 IP，"
                + "但是检测到当前请求 IP 不在配置列表中，如有需要请联系 sms helper");
        errorCodeMap.put(1011, "不存在该 REST API 接口，请核查 REST API 接口说明");
        errorCodeMap.put(1012, "签名格式错误或者签名未审批，签名只能由中英文、数字组成，"
                + "要求2 - 12个字。如果符合签名格式规范，请核查签名是否已审批");
        errorCodeMap.put(1013, "下发短信命中了频率限制策略，可自行到控制台调整短信频率限制策略，如有其他需求请联系 sms helper");
        errorCodeMap.put(1014, "模版未审批或请求的内容与审核通过的模版内容不匹配，请参考 1014错误详解");
        errorCodeMap.put(1015, "手机号在黑名单库中，通常是用户退订或者命中运营商黑名单导致的，可联系 sms helper 解决");
        errorCodeMap.put(1016, "手机号格式错误，请参考 1016错误详解");
        errorCodeMap.put(1017, "请求的短信内容太长，短信长度规则请参考 国内短信内容长度计算规则 或 国际/港澳台短信内容长度计算规则");
        errorCodeMap.put(1019, "sdkappid 不存在");
        errorCodeMap.put(1020, "sdkappid 已禁用，此 sdkappid 禁止提供服务，如有需要请联系 sms helper");
        errorCodeMap.put(1021, "请求发起时间不正常，通常是由于您的服务器时间与腾讯云服务器时间差异超过10分钟导致的，"
                + "请核对服务器时间及 API 接口中的时间字段是否正常");
        errorCodeMap.put(1022, "业务短信日下发条数超过设定的上限，可自行到控制台调整短信频率限制策略");
        errorCodeMap.put(1023, "单个手机号30秒内下发短信条数超过设定的上限，可自行到控制台调整短信频率限制策略");
        errorCodeMap.put(1024, "单个手机号1小时内下发短信条数超过设定的上限，可自行到控制台调整短信频率限制策略");
        errorCodeMap.put(1025, "单个手机号日下发短信条数超过设定的上限，可自行到控制台调整短信频率限制策略");
        errorCodeMap.put(1026, "单个手机号下发相同内容超过设定的上限，可自行到控制台调整短信频率限制策略");
        errorCodeMap.put(1029, "营销短信发送时间限制，为避免骚扰用户，营销短信只允许在8点到22点发送");
        errorCodeMap.put(1030, "不支持该请求");
        errorCodeMap.put(1031, "套餐包余量不足，请 购买套餐包");
        errorCodeMap.put(1032, "个人用户没有发营销短信的权限，请参考 个人认证和企业认证权益区别");
        errorCodeMap.put(1033, "欠费被停止服务，可自行登录腾讯云充值来缴清欠款");
        errorCodeMap.put(1034, "群发请求里既有国内手机号也有国际手机号，国内和国际手机号请分开发送");
        errorCodeMap.put(1036, "单个模板变量字符数超过12个，如需调整限制，可联系 sms helper 解决");
        errorCodeMap.put(1045, "不支持该地区短信下发");
        errorCodeMap.put(1046, "调用群发 API 接口单次提交的手机号个数超过200个，请遵守 API 接口说明 规范");
        errorCodeMap.put(1047, "国际/港澳台短信日下发条数被限制，如需调整限制，可联系 sms helper 解决");
        errorCodeMap.put(60008, "处理请求超时，请参考 60008错误详解");
    }
}
